home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
C++
/
Applications
/
PICSee Dust 1.01
/
Quaternary Source
/
GraphicsBuffers.c
< prev
next >
Wrap
Text File
|
1995-11-24
|
20KB
|
687 lines
/*
GraphicsBuffer.c file, Macintosh platform version.
by Hiep Dam
Version 4.0
Last update: Sept 1995
Copyright ©1995 by Hiep Dam, All Rights Reserved
You may freely use GraphicsBuffers.h, GraphicsBuffers.c
in your own applications.
Version History
1.0 94? Private work.
2.0 Late 94? Changed to GrafixInfo. Added stuff, but still private
and not yet released.
3.0 6/23/95 First public release, changed name to GraphicsBuffers
and added A LOT more stuff and optimizations, including
assembly routines.
3.0.1 6/23/95 Added a few assertions, which 1) Popped open a bug or so
which was previously "hidden" and 2) Revealed a subtle
problem with the 2, 4 and 8 pixel width multiple
restriction (i.e. clipping still might interefere
with the width multiple restriction! aargh!). Ah, the
value of assertions...
You can workaround the clip problem by making sure
you never need to clip your sprite (ie all parts of
it will always be on the screen); that or make sure
that as it moves off the boundaries, it moves off in
multiples of 2, 4, or 8 [whichever is required].
3.1 6/30/95 Added and changed a few things; thanks to Macneil
Shonle for his comments and suggestions.
Made many changes for future compatibility with
cross-platform implementations:
- Privatized GraphicsBuffer structure
- Removed SetMonitorDepth()
The code has also been rearranged and cleaned up.
3.1.1 7/3/95 Changed prototypes slightly for cross-platform
compatibility.
With the addition of CP_Data.h, the GraphicsBuffers.h
file is now compatible with Windows. All I have to
do now is to write the Windows implementation of
GraphicsBuffer.c...
4.0 9/28/95 Header file revamped; some routines changed slightly
in parameters.
Contents of GraphicsBuffers.c file cleaned up.
Split up blitters into associated files organized by
depth.
4.0.1 10/31/95 Added gTransferMode support and the Get/Set
GraphicsBuffers field member routines.
4.0.2 11/1/95 Fixed bug in GraphicsBufferBlitter_16.c (the C version
of the 16-bit transparent blitter). Will look for bugs
in all the other files [due to mis-casting of TwoPixelsPtr_16bit]
4.0.3 11/2/95 Fixed minor issues to make code compatible with
Symantec C++/THINK C 8.0
*/
#include "GraphicsBuffers.h"
#include "GraphicsBufferPriv.h"
// ---------------------------------------------------------------------------
#define kStripRowBytesMask 0x7FFF
// ---------------------------------------------------------------------------
// Related to the blitters only.
SignedByte gMMUMode = true32b;
Boolean gNotIn32Mode = false;
short gTransferMode = srcCopy;
BlitInfo mBlitInfo;
// ---------------------------------------------------------------------------
static GBErr UpdateCachedData(
GraphicsBufferPtr buffer,
long cache,
long pixelDepth,
const CP_Rect *bounds);
// ==========================================================================
GBErr InitGraphicsBuffers() {
gMMUMode = GetMMUMode();
gNotIn32Mode = (gMMUMode != true32b);
return(kGBNoErr);
} // END InitGraphicsBuffers
// ---------------------------------------------------------------------------
GBErr NewGraphicsBuffer(
GraphicsBufferPtr *buffer,
CP_ULong pixelDepth,
const CP_Rect *boundsRect,
CP_ULong flags,
CP_ULong cache) {
GraphicsBufferPrivPtr gb;
GBErr err = kGBNoErr;
ASSERT(!(boundsRect == NULL));
ASSERT(!(cache != true && cache != false));
*buffer = NULL;
/* Allocate chunk of memory for a GraphicsBuffer structure */
gb = (GraphicsBufferPrivPtr)NewPtrClear(sizeof(GraphicsBuffer));
if (gb == NULL)
return(kGBNoMemAvailErr); // or call MemError()
gb->gworld = NULL;
err = NewGWorld(&gb->gworld, pixelDepth, boundsRect, NULL, NULL, flags);
if (err != noErr)
return(kGBOSErr); // or return err itself
else {
err = UpdateCachedData(gb, cache, pixelDepth, boundsRect);
}
*buffer = (GraphicsBufferPtr)gb;
return(err);
} // END NewGraphicsBuffer
// ---------------------------------------------------------------------------
GBErr UpdateGraphicsBuffer(
GraphicsBufferPtr buffer,
long pixelDepth,
const CP_Rect *boundsRect,
long flags,
long cache) {
/*
See NewGraphicsBuffer() for explanation of the arguments.
NOTE: For argument buffer, on input it should be a pointer to an
*existing* GraphicsBuffer.
Notice the difference in arguments here from UpdateGWorld. In
UpdateGWorld, you pass a pointer to a GWorldPtr; here you just
pass a pointer to a GraphicsBuffer (not a pointer to a GraphicsBufferPtr).
Most of the time you'll want to call this after first creating your
GraphicsBuffer, and then having to change the depth of your monitor
and buffer. Pass a depth of 0 and flags of kGBOptimalFlag.
*/
GraphicsBufferPrivPtr gb;
GBErr err;
GWorldFlags gwErr;
ASSERT(!(boundsRect == NULL));
ASSERT(!(cache != true && cache != false));
if (buffer == NULL) return(paramErr);
UnlockGraphicsBuffer(buffer);
gb = (GraphicsBufferPrivPtr)buffer;
gwErr = UpdateGWorld(&gb->gworld, pixelDepth, boundsRect, NULL, NULL, flags);
if (gwErr == gwFlagErr)
return(kGBOSErr); // or QDError()
/* Update cached data */
if (gb->rowAddressOffsets != NULL) {
DisposePtr((Ptr)gb->rowAddressOffsets);
}
err = UpdateCachedData(gb, cache, pixelDepth, boundsRect);
return(kGBNoErr);
} // END UpdateGraphicsBuffer
// ---------------------------------------------------------------------------
GBErr UpdateCachedData(
GraphicsBufferPtr buffer,
long cache,
long pixelDepth,
const CP_Rect *bounds) {
/*
Note: this routine will not work with buffers of type kVideoMemoryBuffer!
*/
GraphicsBufferPrivPtr gb;
GWorldPtr saveWorld;
GDHandle saveDev;
ASSERT(!(buffer == NULL));
ASSERT(!(bounds == NULL));
ASSERT(!(cache != true && cache != false));
gb = (GraphicsBufferPtr)buffer;
(void)LockPixels(GetGWorldPixMap(gb->gworld));
// Make it nice 'n clean: erase gworld first
GetGWorld(&saveWorld, &saveDev);
SetGWorld(gb->gworld, NULL);
EraseRect(&gb->localBounds);
SetGWorld(saveWorld, saveDev);
gb->bufferType = kGraphicsBuffer;
gb->bufferDepth = pixelDepth;
gb->window = NULL;
gb->pixmap = GetGWorldPixMap(gb->gworld);
/* The rowBytes value in the pixmap can't be used directly. The highest
bit is used to determine whether it's a bitmap or pixmap. So we have
to strip this value off, using 7FFF -> 0111 1111 1111 1111
*/
gb->realRowBytes = (kStripRowBytesMask & (**(gb->pixmap)).rowBytes);
gb->rowBytesDiv4 = gb->realRowBytes / 4;
gb->rowBytesDiv2 = gb->realRowBytes / 2;
SetRect(&gb->videoBounds, 0, 0, 0, 0);
gb->localBounds = *bounds;
gb->globBounds = *bounds;
OffsetRect(&gb->localBounds, -gb->localBounds.left,
-gb->localBounds.top);
if (gb->globBounds.left != 0 || gb->globBounds.top != 0)
gb->bufferFlushedTopLeft = false;
else
gb->bufferFlushedTopLeft = true;
if (cache) {
long bufferHeight;
unsigned long i;
gb->bufferCached = true;
// Create our pre-calculated "realRowBytes * vertCoords"
bufferHeight = gb->localBounds.bottom - gb->localBounds.top;
gb->rowAddressOffsets = (unsigned long*)NewPtr
(sizeof(unsigned long) * bufferHeight);
if (gb->rowAddressOffsets == NULL)
return(kGBNoMemAvailErr); // or MemError()
/* Now do the actual precalculations: long multiply */
for (i = 0; i < bufferHeight; i++) {
gb->rowAddressOffsets[i] = gb->realRowBytes * i;
}
}
else {
/* If there is no cache, update flag */
if (gb->rowAddressOffsets == NULL)
gb->bufferCached = false;
else
gb->bufferCached = true;
}
return(noErr);
} // END UpdateCachedData
// ---------------------------------------------------------------------------
GBErr DisposeGraphicsBuffer(GraphicsBufferPtr buffer) {
GraphicsBufferPrivPtr gb;
ASSERT(buffer != NULL);
if (buffer == NULL)
return(kGBParamErr);
gb = (GraphicsBufferPrivPtr)buffer;
/* Dispose contents of GraphicsBuffer */
if (gb->gworld != NULL) {
UnlockPixels(gb->pixmap);
DisposeGWorld(gb->gworld);
}
if (gb->rowAddressOffsets != NULL)
DisposePtr((Ptr)gb->rowAddressOffsets);
/* Dispose GraphicsBuffer itself */
DisposePtr((Ptr)gb);
return(noErr);
} // END DisposeGraphicsBuffer
// ---------------------------------------------------------------------------
GBErr Convert2GraphicsBuffer(
GraphicsBufferPtr *buffer,
CP_Window_Ref srcWind,
const CP_Rect *bounds,
long cache) {
/*
Bounds should be in global coordinates of the window.
*/
// Some local variables...
Rect testRect;
GraphicsBufferPrivPtr gb;
GDHandle monitor;
unsigned long i;
ASSERT(!(bounds == NULL));
ASSERT(!(srcWind == NULL));
ASSERT(!(cache != true && cache != false));
*buffer = NULL;
gb = (GraphicsBufferPrivPtr)NewPtrClear(sizeof(GraphicsBuffer));
if (gb == NULL)
return(kGBNoMemAvailErr); // or MemError() instead
// We're creating a GraphicsBuffer from window and monitor data, so we
// won't need to create a gworld.
gb->gworld = NULL;
gb->window = srcWind;
gb->bufferType = kVideoMemoryBuffer;
/* Given the global bounds of the window, find the corresponding
monitor; we'll assume the window lies wholly inside one monitor
only and it doesn't intersect any other monitors */
monitor = GetDeviceList();
while (monitor != NULL) {
testRect = (**monitor).gdRect;
if (SectRect(bounds, &testRect, &testRect))
break;
monitor = GetNextDevice(monitor);
}
if (monitor == NULL)
return(kGBParamErr);
gb->pixmap = (**monitor).gdPMap;
gb->realRowBytes = (kStripRowBytesMask & (**(gb->pixmap)).rowBytes);
gb->rowBytesDiv4 = gb->realRowBytes / 4;
gb->rowBytesDiv2 = gb->realRowBytes / 2;
gb->videoBounds = (**monitor).gdRect; // or (**gb->pixmap).bounds;
gb->localBounds = *bounds;
gb->globBounds = *bounds;
OffsetRect(&gb->localBounds, -gb->localBounds.left,
-gb->localBounds.top);
if (gb->globBounds.left != 0 || gb->globBounds.top != 0)
gb->bufferFlushedTopLeft = false;
else
gb->bufferFlushedTopLeft = true;
if (cache) {
long bufferHeight = gb->videoBounds.bottom - gb->videoBounds.top;
gb->bufferCached = true;
// Create our pre-calculated "realRowBytes * vertCoords"
gb->rowAddressOffsets = (unsigned long*)NewPtr
(sizeof(unsigned long) * (bufferHeight));
if (gb->rowAddressOffsets == NULL)
return(kGBNoMemAvailErr); // or MemError()
for (i = 0; i < bufferHeight; i++)
gb->rowAddressOffsets[i] = gb->realRowBytes * i;
}
else {
gb->bufferCached = false;
gb->rowAddressOffsets = NULL;
}
*buffer = (GraphicsBufferPtr)gb;
return(noErr);
} // END Convert2GraphicsBuffer
// ---------------------------------------------------------------------------
void SetGraphicsBuffer(const GraphicsBufferPtr buffer) {
/*
Analogous to SetGWorld()
*/
GraphicsBufferPrivPtr gb = (GraphicsBufferPrivPtr)buffer;
ASSERT(buffer != NULL);
if (gb->gworld != NULL)
SetGWorld(gb->gworld, NULL);
} // END SetGraphicsBuffer
// ---------------------------------------------------------------------------
Boolean LockGraphicsBuffer(const GraphicsBufferPtr buffer) {
/*
Analogous to LockGWorld()
*/
GraphicsBufferPrivPtr gb = (GraphicsBufferPrivPtr)buffer;
ASSERT(buffer != NULL);
if (gb->gworld != NULL)
return(LockPixels(gb->pixmap));
else
return(false);
} // END LockGraphicsBuffer
// ---------------------------------------------------------------------------
void UnlockGraphicsBuffer(const GraphicsBufferPtr buffer) {
/*
Analogous to UnlockGWorld()
*/
GraphicsBufferPrivPtr gb = (GraphicsBufferPrivPtr)buffer;
ASSERT(buffer != NULL);
if (gb->gworld != NULL)
UnlockPixels(gb->pixmap);
} // END UnlockGraphicsBuffer
// ---------------------------------------------------------------------------
void SetGraphicsEnvironment(const GraphicsEnvPtr environs) {
ASSERT(environs != NULL);
SetGWorld((GWorldPtr)environs->reserved0, (GDHandle)environs->reserved1);
} // END SetGraphicsEnvironment
// ---------------------------------------------------------------------------
void GetGraphicsEnvironment(GraphicsEnvPtr environs) {
GWorldPtr saveGWorld;
GDHandle saveDevice;
ASSERT(environs != NULL);
GetGWorld(&saveGWorld, &saveDevice);
environs->reserved0 = (void*)saveGWorld;
environs->reserved1 = (void*)saveDevice;
} // END GetGraphicsEnvironment
// ---------------------------------------------------------------------------
void CopyGraphicsBuffer(
GraphicsBufferPtr srcBuffer,
GraphicsBufferPtr destBuffer,
const CP_Rect *srcR,
const CP_Rect *destR) {
GraphicsBufferPrivPtr sBuffer;
GraphicsBufferPrivPtr dBuffer;
ASSERT(!(srcBuffer == NULL));
ASSERT(!(destBuffer == NULL));
ASSERT(!(srcR == NULL));
ASSERT(!(destR == NULL));
sBuffer = (GraphicsBufferPrivPtr)srcBuffer;
dBuffer = (GraphicsBufferPrivPtr)destBuffer;
if (dBuffer->gworld != NULL)
// Just copying between pixmaps.
CopyBits((BitMap*)(*sBuffer->pixmap),
(BitMap*)(*dBuffer->pixmap),
srcR, destR, gTransferMode, NULL);
else if (dBuffer->window != NULL)
// Copying to window
CopyBits((BitMap*)(*sBuffer->pixmap),
(&dBuffer->window->portBits),
srcR, destR, gTransferMode, NULL);
else {
// do nothing...
SysBeep(10);
}
} // END CopyGraphicsBuffer
// ---------------------------------------------------------------------------
void CopyGraphicsBuffer2Window(
GraphicsBufferPtr srcBuffer,
CP_Window_Ref destWind,
const CP_Rect *srcR,
const CP_Rect *destR) {
GraphicsBufferPrivPtr sBuffer;
ASSERT(!(srcBuffer == NULL));
ASSERT(!(destWind == NULL));
ASSERT(!(srcR == NULL));
ASSERT(!(destR == NULL));
sBuffer = (GraphicsBufferPrivPtr)srcBuffer;
LockPixels(GetGWorldPixMap(sBuffer->gworld));
if (sBuffer->gworld != NULL)
CopyBits((BitMap*)&((GrafPtr)sBuffer->gworld)->portBits, &destWind->portBits,
srcR, destR, gTransferMode, NULL);
else if (sBuffer->window != NULL)
CopyBits((&sBuffer->window->portBits), &destWind->portBits,
srcR, destR, gTransferMode, NULL);
else {
SysBeep(10);
}
/*
if (sBuffer->gworld != NULL)
CopyBits((BitMap*)(*sBuffer->pixmap), &destWind->portBits,
srcR, destR, gTransferMode, NULL);
else if (sBuffer->window != NULL)
CopyBits((&sBuffer->window->portBits), &destWind->portBits,
srcR, destR, gTransferMode, NULL);
else {
SysBeep(10);
}
*/
} // END CopyGraphicsBuffer2Window
// ---------------------------------------------------------------------------
void CopyWindow2GraphicsBuffer(
CP_Window_Ref srcWind,
GraphicsBufferPtr destBuffer,
const CP_Rect *srcR,
const CP_Rect *destR) {
GraphicsBufferPrivPtr dBuffer;
ASSERT(!(srcWind == NULL));
ASSERT(!(destBuffer == NULL));
ASSERT(!(srcR == NULL));
ASSERT(!(destR == NULL));
dBuffer = (GraphicsBufferPrivPtr)destBuffer;
if (dBuffer->gworld != NULL)
CopyBits(&srcWind->portBits, (BitMap*)(*dBuffer->pixmap),
srcR, destR, gTransferMode, NULL);
else if (dBuffer->window != NULL)
CopyBits(&srcWind->portBits, (&dBuffer->window->portBits),
srcR, destR, gTransferMode, NULL);
else {
SysBeep(10);
}
} // END CopyWindow2GraphicsBuffer
// ---------------------------------------------------------------------------
void CopyGraphicsBufferRegion(
GraphicsBufferPtr srcBuffer,
GraphicsBufferPtr destBuffer,
const CP_Rect *srcR,
const CP_Rect *destR,
CP_Region_Hdl maskRgn) {
GraphicsBufferPrivPtr sBuffer;
GraphicsBufferPrivPtr dBuffer;
ASSERT(!(srcBuffer == NULL));
ASSERT(!(destBuffer == NULL));
ASSERT(!(srcR == NULL));
ASSERT(!(destR == NULL));
ASSERT(!(maskRgn == NULL));
sBuffer = (GraphicsBufferPrivPtr)srcBuffer;
dBuffer = (GraphicsBufferPrivPtr)destBuffer;
if (dBuffer->gworld != NULL)
CopyBits((BitMap*)(*sBuffer->pixmap),
(BitMap*)(*dBuffer->pixmap),
srcR, destR, gTransferMode, maskRgn);
else if (dBuffer->window != NULL)
CopyBits((BitMap*)(*sBuffer->pixmap),
(&dBuffer->window->portBits),
srcR, destR, gTransferMode, maskRgn);
} // END CopyGraphicsBufferRegion
// ---------------------------------------------------------------------------
void CopyGraphicsBufferMask(
GraphicsBufferPtr srcBuffer,
GraphicsBufferPtr destBuffer,
const CP_Rect *srcR,
const CP_Rect *destR,
GraphicsBufferPtr maskBuffer) {
GraphicsBufferPrivPtr sBuffer;
GraphicsBufferPrivPtr dBuffer;
GraphicsBufferPrivPtr mBuffer;
ASSERT(!(srcBuffer == NULL));
ASSERT(!(destBuffer == NULL));
ASSERT(!(srcR == NULL));
ASSERT(!(destR == NULL));
ASSERT(!(maskBuffer == NULL));
sBuffer = (GraphicsBufferPrivPtr)srcBuffer;
dBuffer = (GraphicsBufferPrivPtr)destBuffer;
mBuffer = (GraphicsBufferPrivPtr)maskBuffer;
if (dBuffer->gworld != NULL)
CopyMask((BitMap*)(*sBuffer->pixmap),
(BitMap*)(*mBuffer->pixmap),
(BitMap*)(*dBuffer->pixmap),
srcR, srcR, destR);
else if (dBuffer->window != NULL)
CopyMask((BitMap*)(*sBuffer->pixmap),
(BitMap*)(*mBuffer->pixmap),
(&dBuffer->window->portBits),
srcR, srcR, destR);
} // END CopyGraphicsBufferMask
// ---------------------------------------------------------------------------
void CopyGraphicsBufferTransparent(
GraphicsBufferPtr srcBuffer,
GraphicsBufferPtr destBuffer,
const CP_Rect *srcR,
const CP_Rect *destR,
GraphicsBufferPtr _notUsed) {
GraphicsBufferPrivPtr sBuffer;
GraphicsBufferPrivPtr dBuffer;
ASSERT(!(srcBuffer == NULL));
ASSERT(!(destBuffer == NULL));
ASSERT(!(srcR == NULL));
ASSERT(!(destR == NULL));
sBuffer = (GraphicsBufferPrivPtr)srcBuffer;
dBuffer = (GraphicsBufferPrivPtr)destBuffer;
if (dBuffer->gworld != NULL)
// Just copying between pixmaps.
CopyBits((BitMap*)(*sBuffer->pixmap),
(BitMap*)(*dBuffer->pixmap),
srcR, destR, transparent, NULL);
else if (dBuffer->window != NULL)
// Copying to window
CopyBits((BitMap*)(*sBuffer->pixmap),
(&dBuffer->window->portBits),
srcR, destR, transparent, NULL);
else {
// do nothing...
}
} // END CopyGraphicsBufferTransparent
// ---------------------------------------------------------------------------
long GetGraphicsBufferType(GraphicsBufferPtr buffer) {
return(((GraphicsBufferPrivPtr)buffer)->bufferType);
} // END GetGraphicsBufferType
// ---------------------------------------------------------------------------
long GetGraphicsBufferDepth(GraphicsBufferPtr buffer) {
return(((GraphicsBufferPrivPtr)buffer)->bufferDepth);
} // END GetGraphicsBufferDepth
// ---------------------------------------------------------------------------
void *GetGraphicsBufferPixelAddress(GraphicsBufferPtr buffer) {
return(GetPixBaseAddr(((GraphicsBufferPrivPtr)buffer)->pixmap));
} // END GetGraphicsBufferPixelAddress
// ---------------------------------------------------------------------------
unsigned long GetGraphicsBufferRowBytes(GraphicsBufferPtr buffer) {
return(((GraphicsBufferPrivPtr)buffer)->realRowBytes);
} // END GetGraphicsBufferRowBytes
// ---------------------------------------------------------------------------
void GetGraphicsBufferBounds(GraphicsBufferPtr buffer, CP_Rect *globalBounds) {
GraphicsBufferPrivPtr gb = (GraphicsBufferPrivPtr)buffer;
*globalBounds = gb->globBounds;
} // END GetGraphicsBufferBounds
// ---------------------------------------------------------------------------
void SetGraphicsBufferTransferMode(short newMode) {
gTransferMode = newMode;
} // END SetGraphicsBufferTransferMode
// ---------------------------------------------------------------------------
short GetGraphicsBufferTransferMode() {
return(gTransferMode);
} // END GetGraphicsBufferTransferMode
// ---------------------------------------------------------------------------
GWorldPtr GetGraphicsBufferGWorld(GraphicsBufferPtr buffer) {
GraphicsBufferPrivPtr gb = (GraphicsBufferPrivPtr)buffer;
return(gb->gworld);
} // END GetGraphicsBufferGWorld
// ==========================================================================
// END GraphicsBuffers.c